package cn.com.dhcc.turbo.service.monitor;

import java.io.StringReader;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import javax.script.ScriptException;

import org.apache.log4j.Logger;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.input.SAXBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import org.xml.sax.InputSource;

import cn.com.dhcc.app.core.CM;
import cn.com.dhcc.app.core.base.IocBean;
import cn.com.dhcc.app.core.exception.DaoException;
import cn.com.dhcc.app.core.exception.NiceException;
import cn.com.dhcc.app.core.exception.ServiceException;
import cn.com.dhcc.app.core.handler.dbhandler.SingleTransationCircleWithOutResult;
import cn.com.dhcc.app.core.handler.modulehandler.WhereCondition;
import cn.com.dhcc.app.core.handler.pagerhandler.Pager;
import cn.com.dhcc.app.core.handler.pagerhandler.PagerData;
import cn.com.dhcc.app.core.service.BaseService;
import cn.com.dhcc.app.core.service.Log;
import cn.com.dhcc.app.core.service.Log.LOGTYPE;
import cn.com.dhcc.app.core.tag.CommonStaticCode.YESNO;
import cn.com.dhcc.app.core.util.BeanMapper;
import cn.com.dhcc.app.core.util.CollectionUtil;
import cn.com.dhcc.app.core.util.JsUtil;
import cn.com.dhcc.app.pub.core.consts.KernelParam;
import cn.com.dhcc.turbo.dao.exch.ExchRelDao;
import cn.com.dhcc.turbo.dao.monitor.QuotaValueOnTimeDao;
import cn.com.dhcc.turbo.dao.registry.NodeInfoDao;
import cn.com.dhcc.turbo.dao.registry.QueueDao;
import cn.com.dhcc.turbo.entity.exch.ExchRel;
import cn.com.dhcc.turbo.entity.exch.NodeLayout;
import cn.com.dhcc.turbo.entity.monitor.Quota;
import cn.com.dhcc.turbo.entity.monitor.QuotaComputeRule;
import cn.com.dhcc.turbo.entity.monitor.QuotaConf;
import cn.com.dhcc.turbo.entity.monitor.QuotaValueHistory;
import cn.com.dhcc.turbo.entity.monitor.QuotaValueOnTime;
import cn.com.dhcc.turbo.entity.monitor.QuotaValueOnTime.QuotaHadlerStatus;
import cn.com.dhcc.turbo.entity.registry.NodeInfo;
import cn.com.dhcc.turbo.entity.registry.SynchronizeInfo.SyncOperType;
import cn.com.dhcc.turbo.entity.registry.SynchronizeInfo.SyncType;
import cn.com.dhcc.turbo.service.monitor.MonitorQuotaStatic.ALERT_PIPELINE;
import cn.com.dhcc.turbo.service.monitor.compute.CommonCompute;
import cn.com.dhcc.turbo.service.monitor.compute.MonitorComputeInterface;
import cn.com.dhcc.turbo.service.monitor.handler.QuotaOntimeValueHandler;
import cn.com.dhcc.turbo.service.registry.NodeInfoService;
import cn.com.dhcc.turbo.service.registry.sync.SynchronizeHandler;

import com.thoughtworks.xstream.XStream;
import com.tongtech.backport.java.util.Arrays;
/**
 * 监控
 * @author qiao
 * @2014-6-3 @下午4:42:02
 */
@Service
public class MonitorService extends BaseService{

	@SuppressWarnings("deprecation")
	Logger logger = Log.getExistLogger(LOGTYPE.MONITOR);
	@Autowired
	NodeInfoService nodeInfoService;
	@Autowired
	private QueueDao queueDao;
	@Autowired
	private ExchRelDao exchRelDao;
	@Autowired
	private NodeInfoDao nodeInfoDao;
	@Autowired
	QuotaValueOnTimeDao quotaOnTimeDao;
	@Autowired
	SynchronizeHandler synchronizeHandler;
	@Autowired 
	@Qualifier(IocBean.DEFAULT_NEEDALERTQUOTA_FILTER)
	INeedAlertQuotaFilter needAlertQuotaFilter;
	
	public MonitorVO getNodeMonitor(String nodeId) throws NiceException,ServiceException{
		return null;
	}
	
	public String getEmailAdressBySysId(String sysId) throws ServiceException{
		String sql = "select adminemail from "+SI_TABLE("TURBO_SYS_INFO")+" where id=?";
		try {
			return  CM.getDao().queryForString("获取系统管理员邮箱", sql, new Object[]{sysId});
		} catch (DaoException e) {
			throw new ServiceException(e);
		}
	}
	
	public QuotaComputeRule getQuotaRuleByRuleSn(Integer ruleSn) throws ServiceException{
		if(ruleSn==null)return null;
		WhereCondition searchParameter = new WhereCondition();
		searchParameter.where().eq("sn", ruleSn);
		try {
			return  CM.getDao().getModule("根据指标id获取指标计算规则", QuotaComputeRule.class, searchParameter);
		} catch (DaoException e) {
			throw new ServiceException("根据指标id获取指标计算规则");
		}
	}
	public QuotaConf getQuotaByQuotaId(String quotaId) throws ServiceException{
		WhereCondition searchParameter = new WhereCondition();
		searchParameter.where().eq("QUOTA_ID", quotaId);
		try {
			return  CM.getDao().getModule("根据指标id获取指标配置", QuotaConf.class, searchParameter);
		} catch (DaoException e) {
			throw new ServiceException("获取指标配置错误");
		}
	}
	public List<QuotaValueOnTime> getQuotaValueOnTimeByQuotaCode(String quotaCode) throws ServiceException{
		try {
			WhereCondition searchParameter = new WhereCondition();
			searchParameter.where().eq("QUOTA_CODE", quotaCode).orderBy(" OWNER_ID,MTIME desc");
			return CM.getDao().listModule("根据指标编码获取指标实时值", QuotaValueOnTime.class, searchParameter);
		} catch (DaoException e) {
			throw new ServiceException("根据指标编码获取指标实时值错误");
		}
	}
	public List<QuotaValueOnTime> getQuotaValueOnTimeByQuotaCodeAndOwnerId(String quotaCode,String ownerId) throws ServiceException{
		try {
			WhereCondition searchParameter = new WhereCondition();
			searchParameter.where().eq("QUOTA_CODE", quotaCode).and().eq("owner_id", ownerId).orderBy("MTIME desc");
			return CM.getDao().listModule("根据指标编码获取指标实时值", QuotaValueOnTime.class, searchParameter);
		} catch (DaoException e) {
			throw new ServiceException("根据指标编码获取指标实时值错误");
		}
	}
	public List<QuotaValueOnTime> getQuotaValueOnTimeByOwnerId(String ownerId) throws ServiceException{
		try {
			WhereCondition searchParameter = new WhereCondition();
			searchParameter.where().eq("owner_id", ownerId).orderBy("MTIME desc");
			return CM.getDao().listModule("根据指标编码获取指标实时值", QuotaValueOnTime.class, searchParameter);
		} catch (DaoException e) {
			throw new ServiceException("根据指标编码获取指标实时值错误");
		}
	}
	public QuotaValueOnTime getQuotaValueOnTimeByQuotaId(String quotaId) throws ServiceException{
		try {
			return CM.getDao().getModuleById("根据id获取指标实时值", QuotaValueOnTime.class, new Object[]{quotaId});
		} catch (DaoException e) {
			throw new ServiceException(e);
		}
	}
	public Quota getQuotaByQuotaCode(String quotaCode) throws ServiceException{
		try {
			WhereCondition searchParameter = new WhereCondition();
			searchParameter.where().eq("CODE", quotaCode).orderBy("MTIME desc");
			return CM.getDao().getModule("根据指标编码获取指标", Quota.class, searchParameter);
		} catch (DaoException e) {
			throw new ServiceException("根据指标编码获取指标错误");
		}
	}
	/**
	 * 获取已经计算过的待告警的指标值
	 * @param needAlertQuotaFilter2 
	 * @return
	 * @throws ServiceException
	 */
	public List<QuotaValueOnTime> getNeedAlertQuotaValue(INeedAlertQuotaFilter needAlertQuotaFilter) throws ServiceException{
		try {
			String sql ="select qt.*,q.alert_handler_times alertHandlerTimes,q.LAST_ALERT_TIME lastAlertTime from "+SI_TABLE("turbo_monitor_ontime ")+"qt, "+SI_TABLE("turbo_monitor_quota ")+" q" +
					" where q.code=qt.QUOTA_CODE and qt.NEEDALERT=? and qt.STATUS=? order by qt. MTIME desc";
			List<QuotaValueOnTime> quotaValueOnTimes = CM.getDao().listModule("获取需要告警处理的监控",sql, QuotaValueOnTime.class, new Object[]{YESNO.YES.getStatus(),QuotaHadlerStatus.WAIT_HANDLER.getCode()});
			if(CollectionUtil.hasElement(quotaValueOnTimes)){
				for (Iterator<QuotaValueOnTime> iterator = quotaValueOnTimes.iterator(); iterator
						.hasNext();) {
					QuotaValueOnTime quotaValueOnTime = iterator.next();
					if(!needAlertQuotaFilter.need(quotaValueOnTime)){
						iterator.remove();
					}
				}
			}
			return quotaValueOnTimes;
		} catch (DaoException e) {
			throw new ServiceException(e);
		}
	}
    public boolean expressCompute(String toComputeJsExpress) throws NiceException{
    	try {
			return (Boolean) JsUtil.simpleComputeExpress(toComputeJsExpress);
		} catch (ScriptException e) {
			throw new NiceException("告警计算出错！");
		}
    }
    /**
     * 根据指标编码获取最新的监控数据
     * @param quotaCode
     * @return
     * @throws ServiceException 
     */
    public List<QuotaValueOnTime> getLastQuotaValueByQuotaCode(String quotaCode) throws ServiceException{
    	String sql = "SELECT t.* FROM "+SI_TABLE("TURBO_MONITOR_ONTIME")+" t" +
    			    " WHERE t.quota_code = ? " +
    			    "       and t.mtime = (select max(mtime) from "+SI_TABLE("TURBO_MONITOR_ONTIME")+" t1 " +
    			    "       where t1.quota_code = t.quota_code)";
    	try {
			return CM.getDao().listModule("根据指标编码获取最新的监控数据", sql, QuotaValueOnTime.class, new Object[]{quotaCode});
		} catch (DaoException e) {
			throw new ServiceException(e);
		}
    }
    /**
     * 根据域编码获取当前域下面系统对应指标的监控数据
     * @param domainId
     * @param quotaCode
     * @return
     * @throws ServiceException 
     */
	public List<QuotaValueOnTime> getLastSysQuotaValueByDomainId(String domainId,String quotaCode) throws ServiceException{
		String sql ="select t.* from "+SI_TABLE("turbo_monitor_ontime")+" t, turbo_domain_info d,turbo_adapter_base a,turbo_adapter_info  aa,turbo_data_category c "+
                    " where c.domain_id = d.id and a.data_code = c.data_code and a.adapter_code = aa.adapter_code and t.owner_id = aa.id "+
                    " and t.quota_code = ? and d.id=? and t.mtime = "+
                    "(select max(tt.mtime) from TURBO_MONITOR_ONTIME tt where tt.quota_code = t.quota_code)";
		try {
			return CM.getDao().listModule("根据域编码获取当前域下面系统对应指标的监控数据", sql, QuotaValueOnTime.class, new Object[]{quotaCode,domainId});
		} catch (DaoException e) {
			throw new ServiceException(e);
		}
	}
	/**
	 * 后台自动告警处理：针对需要发邮件的进行发邮件,已处理的转移到历史记录中
	 * 建议单独线程处理
	 * @throws NiceException 
	 */
	public void monitorOnTimeValueHandle() throws NiceException{
		List<Quota> quotas = null;
		try {
			NodeInfo localNode = nodeInfoDao.getLocalNode();
			if(localNode==null){
				logger.error("指标计算失败：节点未初始化...");
				return;
			}
			quotas = CM.getDao().listModule("获取所有监控指标",Quota.class, null);
			if(CollectionUtil.hasElement(quotas)){
				for (Quota quota:quotas) {
					String code = quota.getCode().toUpperCase();
					QUOTA enumQuota = QUOTA.valueOf(QUOTA.class, code);
					logger.info("开始处理指标数据[("+enumQuota.getCode()+")"+enumQuota.getDesc()+"]...");
					Class<? extends MonitorComputeInterface> handlerClass = enumQuota.getHandler();
					if(handlerClass==null){
						logger.info("使用默认处理逻辑处理指标[("+enumQuota.getCode()+")"+enumQuota.getDesc()+"]...");
						handlerClass =  CommonCompute.class;
					}
					MonitorComputeInterface handler;
					try {
						handler = CM.getBean(handlerClass);
					} catch (Exception e1) {
						logger.error("实例化告警处理器失败",e1);
						return;
					}
					try {
						//按ownerId,时间倒序排序的指标值
						List<QuotaValueOnTime> onTimes = getQuotaValueOnTimeByQuotaCode(quota.getCode());
						if(onTimes==null||onTimes.size()==0)continue;
						QuotaConf conf = getQuotaByQuotaId(quota.getId());
						QuotaComputeRule computeRule = null;
						//handler.merge(onTimes,quota, computeRule, conf);
						if(conf!=null){
							computeRule = getQuotaRuleByRuleSn(conf.getRuleSn());
						}else{
							computeRule = getQuotaRuleByRuleSn(quota.getRuleSug());
						}
						handler.moveToHistory(onTimes, quota, computeRule, conf);
						if(computeRule!=null){
							logger.info("开始对指标[("+enumQuota.getCode()+")"+enumQuota.getDesc()+"]进行阈值计算...");
							handler.computeAlert(onTimes, quota, computeRule, conf);
						}
					} catch (Exception e) {
						logger.error("处理指标[("+enumQuota.getCode()+")"+enumQuota.getDesc()+"]出错",e);
						continue;
					}
					
				}
			}
		} catch (DaoException e) {
			logger.error("监控处理异常,请联系管理员!");
			throw new NiceException("告警处理异常！");
		}
	}
	/**
	 * 告警自动处理，发邮件。如果不需要告警音提示的话，自动将数据转为历史数据。
	 */
	public void autoHhandlerAlert(){
		//按时间倒序排序的指标值
		try {
			NodeInfo localNode = nodeInfoDao.getLocalNode();
			if(localNode==null){
				logger.error("告警提示失败：节点未初始化...");
				return;
			}
			List<QuotaValueOnTime> onTimes = getNeedAlertQuotaValue(needAlertQuotaFilter);
			
			Map<String,QuotaOntimeValueHandler> handlers = new HashMap<String,QuotaOntimeValueHandler>();
			if(CollectionUtil.hasElement(onTimes)){
				logger.info("开始进行自动告警处理...");
				//开始将告警记录分类
				for (Iterator<QuotaValueOnTime> iterator = onTimes.iterator(); iterator.hasNext();) {
					QuotaValueOnTime quotaValueOnTime = iterator.next();
					//已经使用过的告警方式
					List<String> hasUesdAlertPipeLine = getHasUesdAlertPipeLine(quotaValueOnTime.getHasAlertMethod());
					//当前指标需要使用的告警方式
					List<String> alertPipeLine = getAlertPipeLine(quotaValueOnTime.getQuotaCode());
					if(CollectionUtil.hasElement(alertPipeLine)){
						if(CollectionUtil.hasElement(hasUesdAlertPipeLine)&&hasUesdAlertPipeLine.size()==alertPipeLine.size()){
							//所有通道已经处理完毕 ，告警关闭
							quotaOnTimeDao.closeQuotaValueOnTime(quotaValueOnTime);
							continue;
						}
						for (Iterator<String> iterator2 = alertPipeLine.iterator(); iterator2
								.hasNext();) {
							String not =  iterator2.next();
							if(hasUesdAlertPipeLine==null||!hasUesdAlertPipeLine.contains(not)){
								//执行没有使用的告警方式
								if(handlers.get(not)==null){
									Class<? extends QuotaOntimeValueHandler> handler = getOntimeValueHandlerByCode(not);
									if(handler!=null){
										QuotaOntimeValueHandler ontimeValueHandler = CM.getBean(handler);
										handlers.put(not, ontimeValueHandler);
										ontimeValueHandler.registRows(quotaValueOnTime);
									}
								}
							}
						}
					}
				}
			}
			for (Iterator<QuotaOntimeValueHandler> iterator = handlers.values().iterator(); iterator.hasNext();) {
				QuotaOntimeValueHandler handler = iterator.next();
				handler.handler();
			}
		} catch (Exception e) {
			logger.error("告警自动处理异常",e);
		}
	}
	public Class<? extends QuotaOntimeValueHandler> getOntimeValueHandlerByCode(String code){
		ALERT_PIPELINE[] pipelines = ALERT_PIPELINE.values();
		for (int i = 0; i < pipelines.length; i++) {
			if(pipelines[i].getCode().equalsIgnoreCase(code)){
				return pipelines[i].getOntimeValueHandler();
			}
		}
		return null;
	}
	@SuppressWarnings("unchecked")
	public List<String> getHasUesdAlertPipeLine(String usedMethodStr){
		if(StringUtils.hasText(usedMethodStr)){
			return Arrays.asList(usedMethodStr.split(","));
		}
		return null;
	}
	
	@SuppressWarnings("unchecked")
	public List<String> getAlertPipeLine(String quotaCode) throws ServiceException{
		String getCustomAlertPipeLine = "Select c.ALTER_PIPELINE from "+SI_TABLE("TURBO_MONITOR_QUOTA")+" q,"
	                                                                 +SI_TABLE("TURBO_MONITOR_QUOTA_CONF")+" c"+
				                        " where c.QUOTA_ID=q.id and q.CODE=?";
		String customAlertPipeLine;
		try {
			customAlertPipeLine = CM.getDao().queryForString("获取用户配置的告警通道", getCustomAlertPipeLine, new Object[]{quotaCode});
		
			if(!StringUtils.hasText(customAlertPipeLine)){
				String getDefalutAlertPipeLine = "Select q.ALTER_PIPELINE from "+SI_TABLE("TURBO_MONITOR_QUOTA")+" q "+
	                                             " where q.CODE=?";
				customAlertPipeLine = CM.getDao().queryForString("获取默认的告警通道", getDefalutAlertPipeLine, new Object[]{quotaCode});
			}
			if(StringUtils.hasText(customAlertPipeLine)){
				return Arrays.asList(customAlertPipeLine.split(","));
			}else{
				return null;
			}
		} catch (DaoException e) {
			throw new ServiceException(e);
		}
	}
	/**
	 * 将实时数据转移到历史数据
	 * @param quotaValueOnTime
	 * @throws ServiceException
	 */
	public void moveOnTimeMonitorToHistory(final QuotaValueOnTime quotaValueOnTime ) throws ServiceException{
		quotaValueOnTime.setStatus(QuotaHadlerStatus.HAS_HANDLER.getCode());
		final QuotaValueHistory history = new QuotaValueHistory();
		BeanMapper.copy(quotaValueOnTime, history);
		try {
			CM.getDao().doInSingleTransationCircle("将监控数据转移到历史", new SingleTransationCircleWithOutResult() {
				@Override
				public void actionInCircle() throws RuntimeException {
					try {
						CM.getDao().deleteModuleById("删除实时监控数据", quotaValueOnTime);
						CM.getDao().insertModule("插入监控历史数据", history);
					} catch (Exception e) {
						throw new RuntimeException("将实时数据转移到历史失败");
					}
					
				}
			});
		} catch (DaoException e) {
			throw new ServiceException(e);
		}
	}
	/**
	 * 跟新或者添加告警实时值
	 * @param onTime
	 * @throws ServiceException
	 */
	public void insertOrUpdateQuotaOnTime(QuotaValueOnTime onTime) throws ServiceException{
		try {
			CM.getDao().saveOrUpdateModuleById("添加告警实时值", onTime, null);
		} catch (DaoException e) {
			throw new ServiceException(e);
		}
	}
	/**
	 * 跟新或者添加告警实时值
	 * @param onTime
	 * @throws ServiceException
	 */
	public void insertQuotaOnTime(QuotaValueOnTime onTime) throws ServiceException{
		try {
			CM.getDao().insertModule("添加告警实时值", onTime);
		} catch (DaoException e) {
			throw new ServiceException(e);
		}
	}
	/**
	 * 数据发送统计
	 * @param quota_code
	 * @return
	 * @throws ServiceException
	 */
	public List<QuotaValueOnTime> getSendFlowHourList(String quotaCode,String ownerId)
			throws ServiceException {
		try {
			return quotaOnTimeDao.getSendFlowHourList(quotaCode,ownerId);
		} catch (DaoException e) {
			throw new ServiceException("获取数据发送统计失败", e);
		}
	}
	/**
	 * 获取告警列表
	 * @param pager
	 * @param condition
	 * @return
	 * @throws ServiceException
	 */
	public PagerData<QuotaValueOnTime> alertlist(Pager pager,
			WhereCondition condition)throws ServiceException {
		try {
			return quotaOnTimeDao.alertlist(pager, condition);
		} catch (DaoException e) {
			throw new ServiceException("获取告警列表失败", e);
		}
	}
	/**
	 * 关闭告警
	 * @param id
	 * @return
	 * @throws ServiceException
	 */
	public int closeAlert(String id) throws ServiceException {
		try {
			return quotaOnTimeDao.closeAlert(id);
		} catch (DaoException e) {
			throw new ServiceException("关闭告警失败", e);
		}
	}
	/**
	 * 批量关闭
	 * @param ids
	 * @return
	 * @throws ServiceException
	 */
	public int batchCloseAlert(String[] ids) throws ServiceException {
		try {
			return quotaOnTimeDao.batchCloseAlert(ids);
		} catch (DaoException e) {
			throw new ServiceException("批量关闭告警失败", e);
		}
		
	}
	/**
	 * 获取告警历史列表
	 * @param pager
	 * @param condition
	 * @return
	 * @throws ServiceException
	 */
	public PagerData<QuotaValueHistory> historyAlertlist(Pager pager,
			WhereCondition condition) throws ServiceException {
		try {
			return quotaOnTimeDao.historyAlertlist(pager, condition);
		} catch (DaoException e) {
			throw new ServiceException("获取告警历史列表失败", e);
		}
	}

	public int getCountAlert(String ownId) throws ServiceException {
		try {
			return quotaOnTimeDao.getCountAlert(ownId);
		} catch (DaoException e) {
			throw new ServiceException("获取告警历史列表失败", e);
		}
		
	}
	/**
	 * 定时删除已处理告警历史
	 * @throws ServiceException
	 */
	public void timingDelete(String day) throws ServiceException {
		try {
			quotaOnTimeDao.timingDelete(day);
		} catch (DaoException e) {
			throw new ServiceException("定时删除已处理告警历史失败", e);
		}
	}
	/**
	 * 修改指标最后告警时间。
	 * 当告警已被处理后，清空告警最后处理时间和告警处理次数。重新开始计数
	 * @param quota
	 * @param newTime 可以为空
	 * @throws ServiceException
	 */
	public void updateLastAlertTime(Quota quota,Date newTime) throws ServiceException{
		quota.setLastAlertTime(newTime);
		if(newTime==null){
			quota.setAlertHandlerTimes(0);
		}else{
			quota.setAlertHandlerTimes((quota.getAlertHandlerTimes()==null?0:quota.getAlertHandlerTimes())+1);
		}
		try {
			CM.getDao().updateModuleById("修改指标最后告警时间", quota, null);
		} catch (DaoException e) {
			throw new ServiceException("修改指标最后告警时间失败", e);
		}
	}
	/**
	 *  获取全部节点交换关系图
	 * @param nodeId
	 * @return
	 * @throws ServiceException
	 */
	@SuppressWarnings({ "rawtypes" })
	public String getAllNodeLayout() throws ServiceException{
		StringBuilder exchRelXML = new StringBuilder();
		try {
			NodeInfo localNode = nodeInfoDao.getLocalNode();
			NodeLayout nodeLayout = exchRelDao.getNodeLayout(localNode.getId());
			//获得所有关系节点
			 List<ExchRel> relList = exchRelDao.getAllExchRel();
			if(nodeLayout != null){
				String xmlDoc = nodeLayout.getRelNodeLayout();
				  // 创建一个新的字符串
				StringReader read = new StringReader(xmlDoc);
				  // 创建新的输入源SAX 解析器将使用 InputSource 对象来确定如何读取 XML 输入
				InputSource source = new InputSource(read);
				  // 创建一个新的SAXBuilder
				SAXBuilder sb = new SAXBuilder();
				Document doc = sb.build(source);
				   // 取的根元素
				Element root = doc.getRootElement();
				   // 得到根元素所有子元素的集合
				List jiedian = root.getChildren();
					if(jiedian.size() >0){
					 	// 获得XML中的命名空间（XML中未定义可不写）
						 /**
						     * 如要取<rel>下的子元素的名称
						     */
					  	//节点指标数组
						String[] nodeCodes ={"tonglingkq_queue_error_num","tonglingkq_queue_num","ftp_fs_used_rate","gap_status"};
						//通道指标数组
						String[] lineCodes ={"remote_tonglingkq_conn_status","remote_ftp_conn_status","net_conn_status"};
//					 	Element et = (Element) jiedian.get(0);
					 //得到图中各节点id，取各节点与本地节点的交换频率并按从大到小排序,再会三个等级
					  StringBuilder nodes = new StringBuilder();   
					  Map<String,String> map = new HashMap<String,String>();
					   List node = root.getChildren("node");
					   for (int i = 0; i < node.size(); i++) {
						   	boolean isError = false;
						   	boolean isCurrent = false;
						    Element nodeEt = (Element) node.get(i);
						    NodeInfo nodevo = nodeInfoDao.get(nodeEt.getAttributeValue("nodeId"));
							if(nodevo == null){
								continue;
							}
					    	nodes.append("<node");
						    nodes.append(" nodeId='").append(nodeEt.getAttributeValue("nodeId")).append("' ");
						    nodes.append(" name='").append(nodeInfoDao.get(nodeEt.getAttributeValue("nodeId")).getNodeName()).append("' ");
						    nodes.append(" label='").append(nodeInfoDao.get(nodeEt.getAttributeValue("nodeId")).getNodeName()).append("' ");
						    nodes.append(" type='").append(nodeEt.getAttributeValue("type")).append("' ");
						    nodes.append(" selected='").append(nodeEt.getAttributeValue("selected")).append("' ");
						    nodes.append(" x='").append(nodeEt.getAttributeValue("x")).append("' ");
						    nodes.append(" y='").append(nodeEt.getAttributeValue("y")).append("' ");
						    List list = quotaOnTimeDao.getExchRelMonitorShow(nodeCodes,nodeEt.getAttributeValue("nodeId"));
						    if(list.size()>0){
						    	isError = true;
						    }
						    nodes.append(" isError='").append(isError).append("' ");
						    if(nodeEt.getAttributeValue("nodeId").equals(localNode.getId())){
						    	isCurrent = true;
						    }
						    nodes.append(" isCurrent='").append(isCurrent).append("' />");
						    map.put(nodevo.getId(), nodevo.getNodeName());
					   }
					StringBuilder lines = new StringBuilder();
					for (int i = 0; i < relList.size(); i++) {
							ExchRel	exchRel = relList.get(i);
						 	boolean isError = false;
						 	String fromNodeName = map.get(exchRel.getNodeIdCreator());
						 	String toNodeName = map.get(exchRel.getNodeIdTo());
							if(fromNodeName == null || toNodeName == null){
								continue;
							}
							lines.append("<line");
							lines.append(" name='").append(exchRel.getNodeIdCreator()).append("' ");
							lines.append(" fromNode='").append(exchRel.getNodeIdCreator()).append("' ");
							lines.append(" toNode='").append(exchRel.getNodeIdTo()).append("' ");
							//数据交换状态
							QuotaValueOnTime from = quotaOnTimeDao.getOnTime("data_exch_status", exchRel.getNodeIdCreator() + "|" + exchRel.getNodeIdTo());
							QuotaValueOnTime to = quotaOnTimeDao.getOnTime("data_exch_status", exchRel.getNodeIdTo() + "|" + exchRel.getNodeIdCreator());
							if(from != null){
								lines.append(" fromStatus='").append(from.getCurrentValue1()).append("' ");
							}else{
								lines.append(" fromStatus='").append("0").append("' ");
							}
							if(to != null){
								lines.append(" toStatus='").append(to.getCurrentValue1()).append("' ");
							}else{
								lines.append(" toStatus='").append("0").append("' ");
							}
							 if(quotaOnTimeDao.getExchRelMonitorShow(lineCodes,exchRel.getNodeIdCreator() + "|" + exchRel.getNodeIdTo()).size()>0 || quotaOnTimeDao.getExchRelMonitorShow(lineCodes,exchRel.getNodeIdTo() + "|" + exchRel.getNodeIdCreator()).size()>0){
							    	isError = true;
							 }
							lines.append(" isError='").append(isError).append("' ");
							//交换频率等级
							lines.append(" count='").append("3").append("' />");
					}
					   exchRelXML.append("<rel>").append(nodes.toString()).append(lines.toString()).append("</rel>");
				}else{
					exchRelXML.append(xmlDoc);
				}
			}
		} catch (Exception e) {
			throw new ServiceException( "获取交换关系图失败", e);
		}
		return exchRelXML.toString();
	}

	public String getNode(String nodeId)  throws ServiceException{
		StringBuilder statusXML = new StringBuilder();
		try {
			NodeInfo vo = nodeInfoDao.get(nodeId);
			XStream xstream = new XStream();
			xstream.alias("node", NodeInfo.class);
			String nodeXml = xstream.toXML(vo);
			//节点异常信息
			 String[] nodeCodes ={"tonglingkq_queue_error_num","tonglingkq_queue_num","ftp_fs_used_rate","gap_status"};
			statusXML.append("<status>");
			List<QuotaValueOnTime> list = quotaOnTimeDao.getExchRelMonitorShow(nodeCodes,nodeId);
			if(list.size()>0){
				 statusXML.append("<excptions>");
		    	for (Iterator<QuotaValueOnTime> iterator = list.iterator(); iterator.hasNext();) {
		    		QuotaValueOnTime ontime = iterator.next();
		    		String msg = "";
		    		if(ontime.getQuotaCode().equals("gap_status")){
		    			msg = "无法连接";
		    		}else{
		    			msg = ontime.getCurrentValue1();
		    		}
					statusXML.append("<excption label='").append(ontime.getQuotaName()).append("' info='").append(msg+"' />");
				}
			    statusXML.append("</excptions>");
			 }
			statusXML.append(nodeXml);
			statusXML.append("</status>");
		} catch (DaoException e) {
			logger.error("获取节点信息失败", e);
			throw new ServiceException("获取节点信息失败", e);
		}
		return statusXML.toString();
	}

	public String getLine(String fromNodeId,String toNodeId) throws ServiceException{
		StringBuilder lineXML = new StringBuilder();
		try {
			String ownerId1 = "";
			String ownerId2 = "";
			ownerId1 = fromNodeId + "|" + toNodeId;
			ownerId2 =  toNodeId+ "|" + fromNodeId;
			
			//拼接通道信息，包括异常信息和24小时数据交换统计
			String[] lineCodes ={"remote_tonglingkq_conn_status","remote_ftp_conn_status","net_conn_status"};
			List<QuotaValueOnTime> sendList = quotaOnTimeDao.getSendFlowHourList("send_flow_hour_for_node",ownerId1);// 远端节点数据发送量
			List<QuotaValueOnTime> recvList = quotaOnTimeDao .getSendFlowHourList("send_flow_hour_for_node",ownerId2);// 远端节点数据接收量
			List<QuotaValueOnTime> list = quotaOnTimeDao.getExchRelMonitorShow(lineCodes,ownerId1);//通道异常列表
			if(list.size() == 0){
				list = quotaOnTimeDao.getExchRelMonitorShow(lineCodes,ownerId2);
			}
			lineXML.append("<line>");
			NodeInfo from = nodeInfoDao.get(fromNodeId);
			NodeInfo to = nodeInfoDao.get(toNodeId);
			lineXML.append("<stat fromName='").append(from.getNodeName()).append("' toName='").append(to.getNodeName()).append("'>");
			for(int i=0 ; i < 24;i++){
				QuotaValueOnTime send = sendList.get(i);
				QuotaValueOnTime recv = recvList.get(i);
				lineXML.append("<node datetime='").append(Integer.parseInt(send.getStime())).append("' data1='").append(send.getSumval()).append("' data2='").append(recv.getSumval()+"' />");
			}
			lineXML.append("</stat>");
			if(list.size()>0){
				lineXML.append("<excptions>");
		    	for (Iterator<QuotaValueOnTime> iterator = list.iterator(); iterator.hasNext();) {
		    		QuotaValueOnTime ontime = iterator.next();
		    		lineXML.append("<excption name='").append(ontime.getQuotaName()).append("' info='").append(ontime.getAlertMsg()+"' />");
				}
		    	lineXML.append("</excptions>");
			 }
			lineXML.append("</line>");
		} catch (DaoException e) {
			logger.error("获取节点信息失败", e);
			throw new ServiceException("获取节点信息失败", e);
		}
		return lineXML.toString();
	}
	
	/**
	 * 节点关系图xml 根据节点id在节点关系图xml中筛选关系节点，重新生成关系图
	 * @param nodeId 节点id
	 * @param xmlDoc 节点关系图xml
	 * @return
	 */
	@SuppressWarnings({ "rawtypes" })
	public  String forExchRelXML(String nodeId,String xmlDoc) {
		StringBuilder exchRelXML = new StringBuilder();
		// 创建一个新的字符串
		StringReader read = new StringReader(xmlDoc);
		// 创建新的输入源SAX 解析器将使用 InputSource 对象来确定如何读取 XML 输入
		InputSource source = new InputSource(read);
		// 创建一个新的SAXBuilder
		SAXBuilder sb = new SAXBuilder();
		try {
		//获得所有关系节点
		 List<ExchRel> relList = exchRelDao.getAllExchByNodeId(nodeId);
		 // 通过输入源构造一个Document
		 Document doc = sb.build(source);
		 // 取的根元素
		 Element root = doc.getRootElement();
		 // 得到根元素所有子元素的集合
		 List jiedian = root.getChildren();
		 if(jiedian.size() > 0){
			 // 获得XML中的命名空间（XML中未定义可不写）
//			 Namespace ns = root.getNamespace();
//			 Element et = null;
			 /**
			 * 如要取<rel>下的子元素的名称
			 */
//			 et = (Element) jiedian.get(0);
			 StringBuilder nodes = new StringBuilder(); 
			//节点指标数组
				String[] nodeCodes ={"tonglingkq_queue_error_num","tonglingkq_queue_num","ftp_fs_used_rate","gap_status"};
				//通道指标数组
				String[] lineCodes ={"remote_tonglingkq_conn_status","remote_ftp_conn_status","net_conn_status"};
			 List node = root.getChildren("node");
			 Map<String,String> map = new HashMap<String,String>();
			 for (int i = 0; i < node.size(); i++) {
				Element nodeEt = (Element) node.get(i);
				NodeInfo nodevo = nodeInfoDao.get(nodeEt.getAttributeValue("nodeId"));
				if(nodevo == null){
					continue;
				}
				if(nodeId.equals(nodeEt.getAttributeValue("nodeId")) || (!nodeId.equals(nodeEt.getAttributeValue("nodeId")) && exchRelDao.check(nodeEt.getAttributeValue("nodeId"),nodeId) != null)){
				 	boolean isError = false;
					boolean isCurrent = false;
					nodes.append("<node");
					nodes.append(" nodeId='").append(nodeEt.getAttributeValue("nodeId")).append("' ");
					nodes.append(" name='").append(nodeInfoDao.get(nodeEt.getAttributeValue("nodeId")).getNodeName()).append("' ");
					nodes.append(" label='").append(nodeInfoDao.get(nodeEt.getAttributeValue("nodeId")).getNodeName()).append("' ");
					nodes.append(" type='").append(nodeEt.getAttributeValue("type")).append("' ");
					nodes.append(" selected='").append(nodeEt.getAttributeValue("selected")).append("' ");
					nodes.append(" x='").append(nodeEt.getAttributeValue("x")).append("' ");
					nodes.append(" y='").append(nodeEt.getAttributeValue("y")).append("' ");
					 if(nodeEt.getAttributeValue("nodeId").equals(nodeId)){
					    	isCurrent = true;
					    }
					nodes.append(" isCurrent='").append(isCurrent).append("' ");
					if(quotaOnTimeDao.getExchRelMonitorShow(nodeCodes,nodeEt.getAttributeValue("nodeId")).size()>0){
					    	isError = true;
					}
					nodes.append(" isError='").append(isError).append("' />");
				}
				map.put(nodevo.getId(), nodevo.getNodeName());
			 }
			 StringBuilder lines = new StringBuilder();
			 for (int i = 0; i < relList.size(); i++) {
				 	ExchRel	exchRel = relList.get(i);
					String fromNodeName = map.get(exchRel.getNodeIdCreator());
				 	String toNodeName = map.get(exchRel.getNodeIdTo());
					if(fromNodeName == null || toNodeName == null){
						continue;
					}
				 	boolean isError =  false;
					lines.append("<line");
					lines.append(" name='").append(exchRel.getNodeIdCreator()).append("' ");
					lines.append(" fromNode='").append(exchRel.getNodeIdCreator()).append("' ");
					lines.append(" toNode='").append(exchRel.getNodeIdTo()).append("' ");
					//数据交换状态
					QuotaValueOnTime from = quotaOnTimeDao.getOnTime("data_exch_status", exchRel.getNodeIdCreator() + "|" + exchRel.getNodeIdTo());
					QuotaValueOnTime to = quotaOnTimeDao.getOnTime("data_exch_status", exchRel.getNodeIdTo() + "|" + exchRel.getNodeIdCreator());
					if(from != null){
						lines.append(" fromStatus='").append(from.getCurrentValue1()).append("' ");
					}else{
						lines.append(" fromStatus='").append("0").append("' ");
					}
					if(to != null){
						lines.append(" toStatus='").append(to.getCurrentValue1()).append("' ");
					}else{
						lines.append(" toStatus='").append("0").append("' ");
					}
//					lines.append(" fromStatus='").append("0").append("' ");
//					lines.append(" toStatus='").append("1").append("' ");
					 if(quotaOnTimeDao.getExchRelMonitorShow(lineCodes,exchRel.getNodeIdCreator() + "|" + exchRel.getNodeIdTo()).size()>0 || quotaOnTimeDao.getExchRelMonitorShow(lineCodes,exchRel.getNodeIdTo() + "|" + exchRel.getNodeIdCreator()).size()>0){
					    	isError = true;
					 }
					lines.append(" isError='").append(isError).append("' ");
					lines.append(" count='").append("3").append("' />");
			 }
			 	exchRelXML.append("<rel>").append(nodes.toString()).append(lines.toString()).append("</rel>");
		 	}else{
		 		 exchRelXML.append("<rel>").append("</rel>");
			}
		} catch (Exception e) {
			logger.error(e);
		}
		return exchRelXML.toString();
	}
	public QUOTA[] getSyncQuotas(){
		QUOTA quotas[] ;
		int tlqEnable = KernelParam.tlqTransportPipelineEnable;
		if(tlqEnable == 1){
			quotas= new QUOTA[] { 
					QUOTA.TONGLINGKQ_CONN_STATUS,
//					QUOTA.TONGLINGKQ_QUEUE_NUM,
					QUOTA.TONGLINGKQ_QUEUE_STATUS,
					QUOTA.FTP_FS_USED_RATE,
					QUOTA.FTP_CONN_STATUS,
					QUOTA.SEND_FLOW_HOUR_FOR_NODE,
					QUOTA.NET_CONN_STATUS,
					QUOTA.DATA_EXCH_STATUS,
					QUOTA.REMOTE_FTP_CONN_STATUS,
					QUOTA.REMOTE_TONGLINGKQ_CONN_STATUS
				};
		}else{
			quotas= new QUOTA[] { 
					QUOTA.FTP_FS_USED_RATE,
					QUOTA.FTP_CONN_STATUS,
					QUOTA.SEND_FLOW_HOUR_FOR_NODE,
					QUOTA.NET_CONN_STATUS,
					QUOTA.DATA_EXCH_STATUS,
					QUOTA.REMOTE_FTP_CONN_STATUS
				};
		}
		return quotas;
	}
	/**
	 * 向管理节点和交换节点同步数据
	 */
	public void syncToNodes(){
		try {
			QUOTA quotas[] = getSyncQuotas();
			NodeInfo localNode = nodeInfoService.getLocalNode();
			if(localNode==null){
				logger.error("指标值同步失败：节点未初始化...");
				return;
			}
//			NodeInfo pNode = nodeInfoService.get(localNode.getPid());
			List<NodeInfo> list = nodeInfoService.getAllLocalExchNodeList(localNode.getId());
			//OwnerId为65位的监控信息,OwnerId为65位的是监控图上的信息,只有这个地方是65位OwnerId
			for (Iterator<NodeInfo> nodeIterator = list.iterator(); nodeIterator.hasNext();) {
				NodeInfo nodeInfo = nodeIterator.next();
				List<QuotaValueOnTime> onTimes = getQuotaValueOnTimeByOwnerId(localNode.getId()+"|"+nodeInfo.getId());
				 if(onTimes==null||onTimes.size()==0)continue;
				 for (Iterator<QuotaValueOnTime> iterator = onTimes.iterator(); iterator.hasNext();) {
				      QuotaValueOnTime onTime =iterator.next();
				      syncOnTime(onTime,nodeInfo);
//				      if(pNode != null && !nodeInfo.getNodeCode().equals(pNode.getNodeCode()) ){
//				    	  System.out.println(pNode.getNodeCode()+"---to----quotaValueOnTime::::"+onTime);
//					      syncOnTime(onTime,pNode);
//					}
				 }
			}
			for(int i = 0 ; i < quotas.length ; i++){
				  List<QuotaValueOnTime> onTimes = getQuotaValueOnTimeByQuotaCodeAndOwnerId(quotas[i].getCode(),localNode.getId());
				  if(onTimes==null||onTimes.size()==0)continue;
				  QuotaValueOnTime onTime = onTimes.get(0);
				  for (Iterator<NodeInfo> nodeIterator = list.iterator(); nodeIterator.hasNext();) {
			     	NodeInfo nodeInfo = nodeIterator.next();
//			     	 System.out.println(nodeInfo.getNodeCode()+"---to-----quotaValueOnTime::::"+onTime);
			     	syncOnTime(onTime,nodeInfo);
				  }
//				  if(pNode != null){
//				  
//					  System.out.println(pNode.getNodeCode()+"---to-----quotaValueOnTime::::"+onTime);
//				      syncOnTime(onTime,pNode);
//			      }
			}
			
		} catch (Exception e) {
			logger.error("指标同步失败", e);
		}
	}
	/**
	 * 全网同步监控数据
	 * @param entity
	 * @throws ServiceException
	 * @throws NiceException
	 */
	public void syncOnTime(final QuotaValueOnTime entity,final  NodeInfo toNode) throws ServiceException, NiceException {
			
		try {
			synchronizeHandler.syncToNodeFromLocalNode(SyncType.MONITOR, toNode, entity, SyncOperType.INSERT,false);
		} catch (NiceException e) {
			logger.error(e);
		}
			
	}
}
